#include "dominion.h"
#include "dominion_helpers.h"
#include "rngs.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>

int adventurerPlay(struct gameState *state)
{
    int currentPlayer = whoseTurn(state);
    int drawntreasure = 0;
    int cardDrawn;
    int temphand[MAX_HAND];
    int res = 0;
    // index of cards in temphand
    int i = 0;

    // Bug in loop: the discard pile should be shuffled back into the deck only
    // once.  Instead, the discard pile is shuffled back as many times as is
    // needed to add two treasure cards to the player's hand.  This causes,
    // among other things, an increase in the total cards in the player's deck,
    // discard pile, and hand, and therefore an increase in the total cards in
    // the game.
    while(drawntreasure<2) {
        // The calls to check() before and after shuffling occurred because
        // there was a mysterious alteration to currentPlayer that seemed to
        // occur in the course of the shuffle() call.  Just as mysteriously, it
        // disappeared.
        check(currentPlayer <= 3, "currentPlayer = %d", currentPlayer);
        //if the deck is empty we need to shuffle discard and add to deck
        if (state->deckCount[currentPlayer] < 1) {
            // If both the deck and the discard pile are empty, there are no
            // more cards to draw.
            if(state->discardCount[currentPlayer] < 1)
                break;
            shuffle(currentPlayer, state);
        }
        check(currentPlayer <= 3, "currentPlayer = %d", currentPlayer);

        // Bug -- no protection for drawCard returning '-1'
        // This could arise if BOTH deck and discard counts are 0, since in
        // that case shuffle() will not add anything to the deck.
        //
        // This shouldn't happen, given the protection for that before the call
        // to shuffle(), above, but it's here just in case.
        if(drawCard(currentPlayer, state) == -1)
            break;

        //top card of hand is most recently drawn card.
        cardDrawn = state->hand[currentPlayer][state->handCount[currentPlayer]-1];
        if (cardDrawn == copper || cardDrawn == silver || cardDrawn == gold) {
            drawntreasure++;
        } else {
            temphand[i]=cardDrawn;
            // this should just remove the top card (the most recently drawn one).
            state->handCount[currentPlayer]++;
            i++;
        }
    }

    // discard all cards in play that have been drawn
    while(i--) {
        state->discard[currentPlayer][state->discardCount[currentPlayer]++]=temphand[i-1];
    }

error:
    return res;
}

int councilRoomPlay(struct gameState *state, int handPos)
{
    int currentPlayer = whoseTurn(state);
    int i;
    //+4 Cards
    for (i = 0; i < 4; i++) {
        drawCard(currentPlayer, state);
    }

    //+1 Buy
    state->numBuys++;

    //Each other player draws a card
    for (i = 0; i < state->numPlayers; i++)
        if ( i != currentPlayer ) {
            drawCard(i, state);
        }

    //put played card in played card pile
    discardCard(handPos, currentPlayer, state, 0);

    return 0;
}

int feastPlay(int choice1, struct gameState *state)
{
    int currentPlayer = whoseTurn(state);
    int temphand[MAX_HAND];
    int i, x;
    //gain card with cost up to 5
    //Backup hand
    for (i = 0; i <= state->handCount[currentPlayer]; i++) {
        temphand[i] = state->hand[currentPlayer][i];//Backup card
        state->hand[currentPlayer][i] = -1;//Set to nothing
    }
    //Backup hand

    //Update Coins for Buy
    updateCoins(currentPlayer, state, 5);
    x = 1;//Condition to loop on
    while( x == 1) {//Buy one card
        if (supplyCount(choice1, state) <= 0) {
            log_info("None of that card left, sorry!");
            log_info("Cards Left: %d", supplyCount(choice1, state));
        } else if (state->coins < getCost(choice1)) {
            printf("That card is too expensive!\n");
            log_info("Coins: %d < %d", state->coins, getCost(choice1));
        } else {
            log_info("Deck Count: %d", state->handCount[currentPlayer] + state->deckCount[currentPlayer] + state->discardCount[currentPlayer]);

            gainCard(choice1, state, 0, currentPlayer);//Gain the card
            x = 0;//No more buying cards

            log_info("Deck Count: %d", state->handCount[currentPlayer] + state->deckCount[currentPlayer] + state->discardCount[currentPlayer]);
        }
    }

    //Reset Hand
    for (i = 0; i <= state->handCount[currentPlayer]; i++) {
        state->hand[currentPlayer][i] = temphand[i];
        temphand[i] = -1;
    }
    //Reset Hand

    return 0;
}

int minePlay(int choice1, int choice2, struct gameState *state, int handPos)
{
    int currentPlayer = whoseTurn(state);
    int i, j;

    j = state->hand[currentPlayer][choice1];  //store card we will trash

    if (state->hand[currentPlayer][choice1] < copper || state->hand[currentPlayer][choice1] > gold) {
        return -1;
    }

    if (choice2 > treasure_map || choice2 < curse) {
        return -1;
    }

    if ( (getCost(state->hand[currentPlayer][choice1]) + 3) > getCost(choice2) ) {
        return -1;
    }

    gainCard(choice2, state, 2, currentPlayer);

    //discard card from hand
    discardCard(handPos, currentPlayer, state, 0);

    //discard trashed card
    for (i = 0; i < state->handCount[currentPlayer]; i++) {
        if (state->hand[currentPlayer][i] == j) {
            discardCard(i, currentPlayer, state, 0);
            break;
        }
    }

    return 0;
}

int remodelPlay(int choice1, int choice2, struct gameState *state, int handPos)
{
    int currentPlayer = whoseTurn(state);
    int i, j;

    j = state->hand[currentPlayer][choice1];  //store card we will trash

    if ( (getCost(state->hand[currentPlayer][choice1]) + 2) > getCost(choice2) ) {
        return -1;
    }

    gainCard(choice2, state, 0, currentPlayer);

    //discard card from hand
    discardCard(handPos, currentPlayer, state, 0);

    //discard trashed card
    for (i = 0; i < state->handCount[currentPlayer]; i++) {
        if (state->hand[currentPlayer][i] == j) {
            discardCard(i, currentPlayer, state, 0);
            break;
        }
    }

    return 0;
}

int smithyPlay(struct gameState *state, int handPos)
{
    int currentPlayer = whoseTurn(state);
    int i;
    //+3 Cards
    for (i = 0; i < 3; i++) {
        drawCard(currentPlayer, state);
    }

    //discard card from hand
    discardCard(handPos, currentPlayer, state, 0);
    return 0;
}

int villagePlay(struct gameState *state, int handPos)
{
    int currentPlayer = whoseTurn(state);

    //+1 Card
    drawCard(currentPlayer, state);

    //+2 Actions
    state->numActions = state->numActions + 2;

    //discard played card from hand
    discardCard(handPos, currentPlayer, state, 0);
    return 0;
}

int baronPlay(int choice1, struct gameState *state, int handPos)
{
    int currentPlayer = whoseTurn(state);

    state->numBuys++;//Increase buys by 1!
    if (choice1 > 0) { //Boolean true or going to discard an estate
        int p = 0;//Iterator for hand!
        int card_not_discarded = 1;//Flag for discard set!
        while(card_not_discarded) {
            if (state->hand[currentPlayer][p] == estate) { //Found an estate card!
                state->coins += 4;//Add 4 coins to the amount of coins
                state->discard[currentPlayer][state->discardCount[currentPlayer]] = state->hand[currentPlayer][p];
                state->discardCount[currentPlayer]++;
                for (; p < state->handCount[currentPlayer]; p++) {
                    state->hand[currentPlayer][p] = state->hand[currentPlayer][p+1];
                }
                state->hand[currentPlayer][state->handCount[currentPlayer]] = -1;
                state->handCount[currentPlayer]--;
                card_not_discarded = 0;//Exit the loop
            } else if (p > state->handCount[currentPlayer]) {
                log_info("No estate cards in your hand, invalid choice\nMust gain an estate if there are any");
                if (supplyCount(estate, state) > 0) {
                    gainCard(estate, state, 0, currentPlayer);
                    state->supplyCount[estate]--;//Decrement estates
                    if (supplyCount(estate, state) == 0) {
                        isGameOver(state);
                    }
                }
                card_not_discarded = 0;//Exit the loop
            }

            else {
                p++;//Next card
            }
        }
    }

    else {
        if (supplyCount(estate, state) > 0) {
            gainCard(estate, state, 0, currentPlayer);//Gain an estate
            state->supplyCount[estate]--;//Decrement Estates
            if (supplyCount(estate, state) == 0) {
                isGameOver(state);
            }
        }
    }

    return 0;
}

int greatHallPlay(struct gameState *state, int handPos)
{
    int currentPlayer = whoseTurn(state);
    //+1 Card
    drawCard(currentPlayer, state);

    //+1 Actions
    state->numActions++;

    //discard card from hand
    discardCard(handPos, currentPlayer, state, 0);
    return 0;
}

int tributePlay(struct gameState *state, int handPos)
{
    int currentPlayer = whoseTurn(state);
    int nextPlayer = currentPlayer + 1;
    int tributeRevealedCards[2] = {-1, -1};
    int i;

    if ((state->discardCount[nextPlayer] + state->deckCount[nextPlayer]) <= 1) {
        if (state->deckCount[nextPlayer] > 0) {
            tributeRevealedCards[0] = state->deck[nextPlayer][state->deckCount[nextPlayer]-1];
            state->deckCount[nextPlayer]--;
        } else if (state->discardCount[nextPlayer] > 0) {
            tributeRevealedCards[0] = state->discard[nextPlayer][state->discardCount[nextPlayer]-1];
            state->discardCount[nextPlayer]--;
        } else {
            //No Card to Reveal
            log_info("No cards to reveal");
        }
    }

    else {
        if (state->deckCount[nextPlayer] == 0) {
            for (i = 0; i < state->discardCount[nextPlayer]; i++) {
                state->deck[nextPlayer][i] = state->discard[nextPlayer][i];//Move to deck
                state->deckCount[nextPlayer]++;
                state->discard[nextPlayer][i] = -1;
                state->discardCount[nextPlayer]--;
            }

            shuffle(nextPlayer,state);//Shuffle the deck
        }
        tributeRevealedCards[0] = state->deck[nextPlayer][state->deckCount[nextPlayer]-1];
        state->deck[nextPlayer][state->deckCount[nextPlayer]--] = -1;
        state->deckCount[nextPlayer]--;
        tributeRevealedCards[1] = state->deck[nextPlayer][state->deckCount[nextPlayer]-1];
        state->deck[nextPlayer][state->deckCount[nextPlayer]--] = -1;
        state->deckCount[nextPlayer]--;
    }

    if (tributeRevealedCards[0] == tributeRevealedCards[1]) { //If we have a duplicate card, just drop one
        state->playedCards[state->playedCardCount] = tributeRevealedCards[1];
        state->playedCardCount++;
        tributeRevealedCards[1] = -1;
    }

    for (i = 0; i <= 2; i ++) {
        if (tributeRevealedCards[i] == copper || tributeRevealedCards[i] == silver || tributeRevealedCards[i] == gold) { //Treasure cards
            state->coins += 2;
        }

        else if (tributeRevealedCards[i] == estate || tributeRevealedCards[i] == duchy || tributeRevealedCards[i] == province || tributeRevealedCards[i] == gardens || tributeRevealedCards[i] == great_hall) { //Victory Card Found
            drawCard(currentPlayer, state);
            drawCard(currentPlayer, state);
        } else { //Action Card
            state->numActions = state->numActions + 2;
        }
    }

    return 0;
}

int ambassadorPlay(int choice1, int choice2, struct gameState *state, int handPos)
{
    int currentPlayer = whoseTurn(state);
    int i, j;

    j = 0;		//used to check if player has enough cards to discard

    if (choice2 > 2 || choice2 < 0) {
        return -1;
    }

    if (choice1 == handPos) {
        return -1;
    }

    for (i = 0; i < state->handCount[currentPlayer]; i++) {
        if (i != handPos && i == state->hand[currentPlayer][choice1] && i != choice1) {
            j++;
        }
    }
    if (j < choice2) {
        return -1;
    }

    log_info("Player %d reveals card number: %d", currentPlayer, state->hand[currentPlayer][choice1]);

    //increase supply count for choosen card by amount being discarded
    state->supplyCount[state->hand[currentPlayer][choice1]] += choice2;

    //each other player gains a copy of revealed card
    for (i = 0; i < state->numPlayers; i++) {
        if (i != currentPlayer) {
            gainCard(state->hand[currentPlayer][choice1], state, 0, i);
        }
    }

    //discard played card from hand
    discardCard(handPos, currentPlayer, state, 0);

    //trash copies of cards returned to supply
    for (j = 0; j < choice2; j++) {
        for (i = 0; i < state->handCount[currentPlayer]; i++) {
            if (state->hand[currentPlayer][i] == state->hand[currentPlayer][choice1]) {
                discardCard(i, currentPlayer, state, 1);
                break;
            }
        }
    }

    return 0;
}

int embargoPlay(int choice1, struct gameState *state, int handPos)
{
    int currentPlayer = whoseTurn(state);

    //+2 Coins
    state->coins = state->coins + 2;

    //see if selected pile is in play
    if ( state->supplyCount[choice1] == -1 ) {
        return -1;
    }

    //add embargo token to selected supply pile
    state->embargoTokens[choice1]++;

    //trash card
    discardCard(handPos, currentPlayer, state, 1);
    return 0;
}

int outpostPlay(struct gameState *state, int handPos)
{
    int currentPlayer = whoseTurn(state);

    //set outpost flag
    state->outpostPlayed++;

    //discard card
    discardCard(handPos, currentPlayer, state, 0);
    return 0;
}

int salvagerPlay(int choice1, struct gameState *state, int handPos)
{
    int currentPlayer = whoseTurn(state);

    //+1 buy
    state->numBuys++;

    if (choice1) {
        //gain coins equal to trashed card
        state->coins = state->coins + getCost( handCard(choice1, state) );
        //trash card
        discardCard(choice1, currentPlayer, state, 1);
    }

    //discard card
    discardCard(handPos, currentPlayer, state, 0);
    return 0;
}

int seaHagPlay(struct gameState *state)
{
    int currentPlayer = whoseTurn(state);
    int i;

    for (i = 0; i < state->numPlayers; i++) {
        if (i != currentPlayer) {
            state->discard[i][state->discardCount[i]] = state->deck[i][state->deckCount[i]--];
            state->deckCount[i]--;
            state->discardCount[i]++;
            state->deck[i][state->deckCount[i]--] = curse;//Top card now a curse
        }
    }
    return 0;
}

int seaHagPlay_fixed(struct gameState *state)
{
    int currentPlayer = whoseTurn(state);
    int i;

    for (i = 0; i < state->numPlayers; i++) {
        if (i != currentPlayer) {
            state->discard[i][state->discardCount[i]] = state->deck[i][state->deckCount[i] - 1];
            state->discardCount[i]++;
            state->deck[i][state->deckCount[i] - 1] = curse;//Top card now a curse
        }
    }
    return 0;
}

int treasureMapPlay(struct gameState *state, int handPos)
{
    int currentPlayer = whoseTurn(state);
    int i, idx;

    //search hand for another treasure_map
    idx = -1;
    for (i = 0; i < state->handCount[currentPlayer]; i++) {
        if (state->hand[currentPlayer][i] == treasure_map && i != handPos) {
            idx = i;
            break;
        }
    }
    if (idx > -1) {
        //trash both treasure cards
        discardCard(handPos, currentPlayer, state, 1);
        discardCard(idx, currentPlayer, state, 1);

        //gain 4 Gold cards
        for (i = 0; i < 4; i++) {
            gainCard(gold, state, 1, currentPlayer);
        }

        //return success
        return 1;
    }

    //no second treasure_map found in hand
    return -1;
}

int cutpursePlay(struct gameState *state, int handPos)
{
    int currentPlayer = whoseTurn(state);
    int i, j, k;

    updateCoins(currentPlayer, state, 2);

    for (i = 0; i < state->numPlayers; i++) {
        if (i != currentPlayer) {
            for (j = 0; j < state->handCount[i]; j++) {
                if (state->hand[i][j] == copper) {
                    discardCard(j, i, state, 0);
                    break;
                }
                if (j == state->handCount[i]) {
                    for (k = 0; k < state->handCount[i]; k++) {
                        log_info("Player %d reveals card number %d", i, state->hand[i][k]);
                    }
                    break;
                }
            }
        }
    }

    //discard played card from hand
    discardCard(handPos, currentPlayer, state, 0);

    return 0;
}

int minionPlay(int choice1, int choice2, struct gameState *state, int handPos)
{
    int i, j;
    int currentPlayer = whoseTurn(state);

    //+1 action
    state->numActions++;

    //discard card from hand
    discardCard(handPos, currentPlayer, state, 0);

    //+2 coins
    if (choice1) {
        state->coins = state->coins + 2;
    }

    //discard hand, redraw 4, other players with 5+ cards discard hand and draw 4
    else if (choice2) {
        //discard hand
        while(numHandCards(state) > 0) {
            discardCard(handPos, currentPlayer, state, 0);
        }

        //draw 4
        for (i = 0; i < 4; i++) {
            drawCard(currentPlayer, state);
        }

        //other players discard hand and redraw if hand size > 4
        for (i = 0; i < state->numPlayers; i++) {
            if (i != currentPlayer) {
                if ( state->handCount[i] > 4 ) {
                    // discard hand
                    while( state->handCount[i] > 0 ) {
                        discardCard(handPos, i, state, 0);

                        //draw 4
                        for (j = 0; j < 4; j++) {
                            drawCard(i, state);
                        }
                    }
                }
            }
        }

    }
    return 0;
}

int stewardPlay(int choice1, int choice2, int choice3, struct gameState *state, int handPos)
{
    int currentPlayer = whoseTurn(state);
    if (choice1 == 1) {
        //+2 cards
        drawCard(currentPlayer, state);
        drawCard(currentPlayer, state);
    } else if (choice1 == 2) {
        //+2 coins
        state->coins = state->coins + 2;
    } else {
        //trash 2 cards in hand
        discardCard(choice2, currentPlayer, state, 1);
        discardCard(choice3, currentPlayer, state, 1);
    }

    //discard card from hand
    discardCard(handPos, currentPlayer, state, 0);
    return 0;
}

int compare(const void* a, const void* b)
{
    if (*(int*)a > *(int*)b) {
        return 1;
    }
    if (*(int*)a < *(int*)b) {
        return -1;
    }
    return 0;
}

struct gameState* newGame(void)
{
    struct gameState* g = malloc(sizeof(struct gameState));
    return g;
}

int* kingdomCards(int k1, int k2, int k3, int k4, int k5, int k6, int k7,
                  int k8, int k9, int k10)
{
    int* k = malloc(10 * sizeof(int));
    k[0] = k1;
    k[1] = k2;
    k[2] = k3;
    k[3] = k4;
    k[4] = k5;
    k[5] = k6;
    k[6] = k7;
    k[7] = k8;
    k[8] = k9;
    k[9] = k10;
    return k;
}

int initializeGame(int numPlayers, int kingdomCards[10], int randomSeed,
                   struct gameState *state)
{

    int i, j, it;

    //set up random number generator
    SelectStream(1);
    PutSeed((long)randomSeed);

    //check number of players
    if (numPlayers > MAX_PLAYERS || numPlayers < 2) {
        return -1;
    }

    // set number of players
    state->numPlayers = numPlayers;

    //check that selected kingdom cards are different
    for (i = 0; i < 10; i++) {
        for (j = 0; j < 10; j++) {
            if (j != i && kingdomCards[j] == kingdomCards[i]) {
                return -1;
            }
        }
    }

    //initialize supply
    ///////////////////////////////

    //set number of Curse cards
    if (numPlayers == 2) {
        state->supplyCount[curse] = 10;
    } else if (numPlayers == 3) {
        state->supplyCount[curse] = 20;
    } else {
        state->supplyCount[curse] = 30;
    }

    //set number of Victory cards
    if (numPlayers == 2) {
        state->supplyCount[estate] = 8;
        state->supplyCount[duchy] = 8;
        state->supplyCount[province] = 8;
    } else {
        state->supplyCount[estate] = 12;
        state->supplyCount[duchy] = 12;
        state->supplyCount[province] = 12;
    }

    //set number of Treasure cards
    state->supplyCount[copper] = 60 - (7 * numPlayers);
    state->supplyCount[silver] = 40;
    state->supplyCount[gold] = 30;

    //set number of Kingdom cards
    for (i = adventurer; i <= treasure_map; i++) {     	//loop all cards
        for (j = 0; j < 10; j++) {         		//loop chosen cards
            if (kingdomCards[j] == i) {
                //check if card is a 'Victory' Kingdom card
                if (kingdomCards[j] == great_hall || kingdomCards[j] == gardens) {
                    if (numPlayers == 2) {
                        state->supplyCount[i] = 8;
                    } else {
                        state->supplyCount[i] = 12;
                    }
                } else {
                    state->supplyCount[i] = 10;
                }
                break;
            } else { //card is not in the set choosen for the game
                state->supplyCount[i] = -1;
            }
        }
    }

    ////////////////////////
    // supply intialization complete

    // set player decks
    for (i = 0; i < numPlayers; i++) {
        state->deckCount[i] = 0;
        for (j = 0; j < 3; j++) {
            state->deck[i][j] = estate;
            state->deckCount[i]++;
        }
        for (j = 3; j < 10; j++) {
            state->deck[i][j] = copper;
            state->deckCount[i]++;
        }
    }

    //shuffle player decks
    for (i = 0; i < numPlayers; i++) {
        if ( shuffle(i, state) < 0 ) {
            return -1;
        }
    }

    //draw player hands
    for (i = 0; i < numPlayers; i++) {
        //
        //initialize hand size to zero
        state->handCount[i] = 0;
        state->discardCount[i] = 0;
        //draw 5 cards
        // for (j = 0; j < 5; j++)
        //	{
        //	  drawCard(i, state);
        //	}
    }

    //set embargo tokens to 0 for all supply piles
    for (i = 0; i <= treasure_map; i++) {
        state->embargoTokens[i] = 0;
    }

    //initialize first player's turn
    state->outpostPlayed = 0;
    state->phase = 0;
    state->numActions = 1;
    state->numBuys = 1;
    state->playedCardCount = 0;
    state->whoseTurn = 0;
    state->handCount[state->whoseTurn] = 0;
    //int it; move to top

    //Moved draw cards to here, only drawing at the start of a turn
    for (it = 0; it < 5; it++) {
        drawCard(state->whoseTurn, state);
    }

    updateCoins(state->whoseTurn, state, 0);

    return 0;
}

int shuffle(int player, struct gameState *state)
{
    int newDeck[MAX_DECK];
    int newDeckPos = 0;
    int card;
    int i;

    if (state->deckCount[player] < 1) {
        return -1;
    }
    qsort ((void*)(state->deck[player]), state->deckCount[player], sizeof(int), compare);
    /* SORT CARDS IN DECK TO ENSURE DETERMINISM! */

    while (state->deckCount[player] > 0) {
        // Bug here?  Should that be '%' instead of '*'?
        card = floor(Random() * state->deckCount[player]);
        newDeck[newDeckPos] = state->deck[player][card];
        newDeckPos++;
        for (i = card; i < state->deckCount[player]-1; i++) {
            state->deck[player][i] = state->deck[player][i+1];
        }
        state->deckCount[player]--;
    }
    for (i = 0; i < newDeckPos; i++) {
        state->deck[player][i] = newDeck[i];
        state->deckCount[player]++;
    }

    return 0;
}

int playCard(int handPos, int choice1, int choice2, int choice3, struct gameState *state)
{
    int card;
    int coin_bonus = 0; 		//tracks coins gain from actions

    //check if it is the right phase
    if (state->phase != 0) {
        return -1;
    }

    //check if player has enough actions
    if ( state->numActions < 1 ) {
        return -1;
    }

    //get card played
    card = handCard(handPos, state);

    //check if selected card is an action
    if ( card < adventurer || card > treasure_map ) {
        return -1;
    }

    //play card
    if ( cardEffect(card, choice1, choice2, choice3, state, handPos, &coin_bonus) < 0 ) {
        return -1;
    }

    //reduce number of actions
    state->numActions--;

    //update coins (Treasure cards may be added with card draws)
    updateCoins(state->whoseTurn, state, coin_bonus);

    return 0;
}

int buyCard(int supplyPos, struct gameState *state)
{
    int who;
    log_info("Entering buyCard...");

    // I don't know what to do about the phase thing.

    who = state->whoseTurn;

    if (state->numBuys < 1) {
        log_info("You do not have any buys left");
        return -1;
    } else if (supplyCount(supplyPos, state) <1) {
        log_info("There are not any of that type of card left");
        return -1;
    } else if (state->coins < getCost(supplyPos)) {
        log_info("You do not have enough money to buy that. You have %d coins.", state->coins);
        return -1;
    } else {
        state->phase=1;
        //state->supplyCount[supplyPos]--;
        gainCard(supplyPos, state, 0, who); //card goes in discard, this might be wrong.. (2 means goes into hand, 0 goes into discard)

        state->coins = (state->coins) - (getCost(supplyPos));
        state->numBuys--;
        log_info("You bought card number %d for %d coins. You now have %d buys and %d coins.", supplyPos, getCost(supplyPos), state->numBuys, state->coins);
    }

    //state->discard[who][state->discardCount[who]] = supplyPos;
    //state->discardCount[who]++;

    return 0;
}

int numHandCards(struct gameState *state)
{
    return state->handCount[ whoseTurn(state) ];
}

int handCard(int handPos, struct gameState *state)
{
    int currentPlayer = whoseTurn(state);
    return state->hand[currentPlayer][handPos];
}

int supplyCount(int card, struct gameState *state)
{
    return state->supplyCount[card];
}

int fullDeckCount(int player, int card, struct gameState *state)
{
    int i;
    int count = 0;

    for (i = 0; i < state->deckCount[player]; i++) {
        if (state->deck[player][i] == card) {
            count++;
        }
    }

    for (i = 0; i < state->handCount[player]; i++) {
        if (state->hand[player][i] == card) {
            count++;
        }
    }

    for (i = 0; i < state->discardCount[player]; i++) {
        if (state->discard[player][i] == card) {
            count++;
        }
    }

    return count;
}

int whoseTurn(struct gameState *state)
{
    return state->whoseTurn;
}

int endTurn(struct gameState *state)
{
    int k;
    int i;
    int currentPlayer = whoseTurn(state);

    //Discard hand
    for (i = 0; i < state->handCount[currentPlayer]; i++) {
        state->discard[currentPlayer][state->discardCount[currentPlayer]++] = state->hand[currentPlayer][i];//Discard
        state->hand[currentPlayer][i] = -1;//Set card to -1
    }
    state->handCount[currentPlayer] = 0;//Reset hand count

    //Code for determining the player
    if (currentPlayer < (state->numPlayers - 1)) {
        state->whoseTurn = currentPlayer + 1;//Still safe to increment
    } else {
        state->whoseTurn = 0;//Max player has been reached, loop back around to player 1
    }

    state->outpostPlayed = 0;
    state->phase = 0;
    state->numActions = 1;
    state->coins = 0;
    state->numBuys = 1;
    state->playedCardCount = 0;
    state->handCount[state->whoseTurn] = 0;

    //int k; move to top
    //Next player draws hand
    for (k = 0; k < 5; k++) {
        drawCard(state->whoseTurn, state);//Draw a card
    }

    //Update money
    updateCoins(state->whoseTurn, state , 0);

    return 0;
}

int isGameOver(struct gameState *state)
{
    int i;
    int j;

    //if stack of Province cards is empty, the game ends
    if (state->supplyCount[province] == 0) {
        return 1;
    }

    //if three supply pile are at 0, the game ends
    j = 0;
    // Caught bug?  Loop condition used to be 'i < 25'.
    for (i = 0; i < treasure_map + 1; i++) {
        if (state->supplyCount[i] == 0) {
            j++;
        }
    }
    if ( j >= 3) {
        return 1;
    }

    return 0;
}

int scoreFor (int player, struct gameState *state)
{
    int i;
    int score = 0;
    //score from hand
    for (i = 0; i < state->handCount[player]; i++) {
        if (state->hand[player][i] == curse) {
            score = score - 1;
        };
        if (state->hand[player][i] == estate) {
            score = score + 1;
        };
        if (state->hand[player][i] == duchy) {
            score = score + 3;
        };
        if (state->hand[player][i] == province) {
            score = score + 6;
        };
        if (state->hand[player][i] == great_hall) {
            score = score + 1;
        };
        if (state->hand[player][i] == gardens) {
            score = score + ( fullDeckCount(player, 0, state) / 10 );
        };
    }

    //score from discard
    for (i = 0; i < state->discardCount[player]; i++) {
        if (state->discard[player][i] == curse) {
            score = score - 1;
        };
        if (state->discard[player][i] == estate) {
            score = score + 1;
        };
        if (state->discard[player][i] == duchy) {
            score = score + 3;
        };
        if (state->discard[player][i] == province) {
            score = score + 6;
        };
        if (state->discard[player][i] == great_hall) {
            score = score + 1;
        };
        if (state->discard[player][i] == gardens) {
            score = score + ( fullDeckCount(player, 0, state) / 10 );
        };
    }

    //score from deck
    for (i = 0; i < state->discardCount[player]; i++) {
        if (state->deck[player][i] == curse) {
            score = score - 1;
        };
        if (state->deck[player][i] == estate) {
            score = score + 1;
        };
        if (state->deck[player][i] == duchy) {
            score = score + 3;
        };
        if (state->deck[player][i] == province) {
            score = score + 6;
        };
        if (state->deck[player][i] == great_hall) {
            score = score + 1;
        };
        if (state->deck[player][i] == gardens) {
            score = score + ( fullDeckCount(player, 0, state) / 10 );
        };
    }

    return score;
}

int getWinners(int players[MAX_PLAYERS], struct gameState *state)
{
    int i;
    int j;
    int highScore;
    int currentPlayer;

    //get score for each player
    for (i = 0; i < MAX_PLAYERS; i++) {
        //set unused player scores to -9999
        if (i >= state->numPlayers) {
            players[i] = -9999;
        } else {
            players[i] = scoreFor (i, state);
        }
    }

    //find highest score
    j = 0;
    for (i = 0; i < MAX_PLAYERS; i++) {
        if (players[i] > players[j]) {
            j = i;
        }
    }
    highScore = players[j];

    //add 1 to players who had less turns
    currentPlayer = whoseTurn(state);
    for (i = 0; i < MAX_PLAYERS; i++) {
        if ( players[i] == highScore && i > currentPlayer ) {
            players[i]++;
        }
    }

    //find new highest score
    j = 0;
    for (i = 0; i < MAX_PLAYERS; i++) {
        if ( players[i] > players[j] ) {
            j = i;
        }
    }
    highScore = players[j];

    //set winners in array to 1 and rest to 0
    for (i = 0; i < MAX_PLAYERS; i++) {
        if ( players[i] == highScore ) {
            players[i] = 1;
        } else {
            players[i] = 0;
        }
    }

    return 0;
}

int drawCard(int player, struct gameState *state)
{
    check(player <= 3, "player = %d", player);
    int count;
    int deckCounter;
    if (state->deckCount[player] <= 0) { //Deck is empty

        //Step 1 Shuffle the discard pile back into a deck
        int i;
        //Move discard to deck
        for (i = 0; i < state->discardCount[player]; i++) {
            state->deck[player][i] = state->discard[player][i];
            state->discard[player][i] = -1;
        }

        state->deckCount[player] = state->discardCount[player];
        state->discardCount[player] = 0;//Reset discard

        //Shuffle the deck
        shuffle(player, state);//Shuffle the deck up and make it so that we can draw

        log_info("Deck count now: %d", state->deckCount[player]);

        // Why twice?
        state->discardCount[player] = 0;

        //Step 2 Draw Card
        count = state->handCount[player];//Get current player's hand count

        log_info("Current hand count: %d", count);

        deckCounter = state->deckCount[player];//Create a holder for the deck count

        if (deckCounter == 0) {
            return -1;
        }

        state->hand[player][count] = state->deck[player][deckCounter - 1];//Add card to hand
        state->deckCount[player]--;
        state->handCount[player]++;//Increment hand count
    }

    else {
        count = state->handCount[player];//Get current hand count for player
        log_info("Current hand count: %d", count);

        deckCounter = state->deckCount[player];//Create holder for the deck count
        state->hand[player][count] = state->deck[player][deckCounter - 1];//Add card to the hand
        state->deckCount[player]--;
        state->handCount[player]++;//Increment hand count
    }

    return 0;

error:
    return -1;
}

int getCost(int cardNumber)
{
    switch( cardNumber ) {
    case curse:
        return 0;
    case estate:
        return 2;
    case duchy:
        return 5;
    case province:
        return 8;
    case copper:
        return 0;
    case silver:
        return 3;
    case gold:
        return 6;
    case adventurer:
        return 6;
    case council_room:
        return 5;
    case feast:
        return 4;
    case gardens:
        return 4;
    case mine:
        return 5;
    case remodel:
        return 4;
    case smithy:
        return 4;
    case village:
        return 3;
    case baron:
        return 4;
    case great_hall:
        return 3;
    case minion:
        return 5;
    case steward:
        return 3;
    case tribute:
        return 5;
    case ambassador:
        return 3;
    case cutpurse:
        return 4;
    case embargo:
        return 2;
    case outpost:
        return 5;
    case salvager:
        return 4;
    case sea_hag:
        return 4;
    case treasure_map:
        return 4;
    }

    return -1;
}

// Alters variables: state
// Unused variables: bonus
int cardEffect(int card, int choice1, int choice2, int choice3, struct gameState *state, int handPos, int *bonus)
{
    int currentPlayer = whoseTurn(state);
    int nextPlayer = currentPlayer + 1;

    if (nextPlayer > (state->numPlayers - 1)) {
        nextPlayer = 0;
    }

    //uses switch to select card and perform actions
    switch( card ) {
    case adventurer:
        return adventurerPlay(state);
    case council_room:
        return councilRoomPlay(state, handPos);
    case feast:
        return feastPlay(choice1, state);
    case gardens:
        return -1;
    case mine:
        return minePlay(choice1, choice2, state, handPos);
    case remodel:
        return remodelPlay(choice1, choice2, state, handPos);
    case smithy:
        return smithyPlay(state, handPos);
    case village:
        return villagePlay(state, handPos);
    case baron:
        return baronPlay(choice1, state, handPos);
    case great_hall:
        return greatHallPlay(state, handPos);
    case minion:
        return minionPlay(choice1, choice2, state, handPos);
    case steward:
        return stewardPlay(choice1, choice2, choice3, state, handPos);
    case tribute:
        return tributePlay(state, handPos);
    case ambassador:
        return ambassadorPlay(choice1, choice2, state, handPos);
    case cutpurse:
        return cutpursePlay(state, handPos);
    case embargo:
        return embargoPlay(choice1, state, handPos);
    case outpost:
        return outpostPlay(state, handPos);
    case salvager:
        return salvagerPlay(choice1, state, handPos);
    case sea_hag:
        //return seaHagPlay(state);
        return seaHagPlay_fixed(state);
    case treasure_map:
        return treasureMapPlay(state, handPos);
    default:
        return -1;
    }

    //return -1;
}

int discardCard(int handPos, int currentPlayer, struct gameState *state, int trashFlag)
{

    //if card is not trashed, added to Played pile
    if (trashFlag < 1) {
        //add card to played pile
        state->playedCards[state->playedCardCount] = state->hand[currentPlayer][handPos];
        state->playedCardCount++;
    }

    //set played card to -1
    state->hand[currentPlayer][handPos] = -1;

    //remove card from player's hand
    if ( handPos == (state->handCount[currentPlayer] - 1) ) {	//last card in hand array is played
        //reduce number of cards in hand
        state->handCount[currentPlayer]--;
    } else if ( state->handCount[currentPlayer] == 1 ) { //only one card in hand
        //reduce number of cards in hand
        state->handCount[currentPlayer]--;
    } else {
        //replace discarded card with last card in hand
        state->hand[currentPlayer][handPos] = state->hand[currentPlayer][ (state->handCount[currentPlayer] - 1)];
        //set last card to -1
        state->hand[currentPlayer][state->handCount[currentPlayer] - 1] = -1;
        //reduce number of cards in hand
        state->handCount[currentPlayer]--;
    }

    return 0;
}

int gainCard(int supplyPos, struct gameState *state, int toFlag, int player)
{
    //Note: supplyPos is enum of choosen card

    //check if supply pile is empty (0) or card is not used in game (-1)
    if ( supplyCount(supplyPos, state) < 1 ) {
        return -1;
    }

    //added card for [whoseTurn] current player:
    // toFlag = 0 : add to discard
    // toFlag = 1 : add to deck
    // toFlag = 2 : add to hand

    if (toFlag == 1) {
        state->deck[ player ][ state->deckCount[player] ] = supplyPos;
        state->deckCount[player]++;
    } else if (toFlag == 2) {
        state->hand[ player ][ state->handCount[player] ] = supplyPos;
        state->handCount[player]++;
    } else {
        state->discard[player][ state->discardCount[player] ] = supplyPos;
        state->discardCount[player]++;
    }

    //decrease number in supply pile
    state->supplyCount[supplyPos]--;

    return 0;
}

int updateCoins(int player, struct gameState *state, int bonus)
{
    int i;

    //reset coin count
    state->coins = 0;

    //add coins for each Treasure card in player's hand
    for (i = 0; i < state->handCount[player]; i++) {
        if (state->hand[player][i] == copper) {
            state->coins += 1;
        } else if (state->hand[player][i] == silver) {
            state->coins += 2;
        } else if (state->hand[player][i] == gold) {
            state->coins += 3;
        }
    }

    //add bonus
    state->coins += bonus;

    return 0;
}


//end of dominion.c

